package com.tencent.yolov5ncnn

import android.app.Activity
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageFormat
import android.graphics.Matrix
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.media.CamcorderProfile
import android.media.MediaRecorder
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import com.blankj.utilcode.util.ImageUtils
import com.tencent.yolov5ncnn.MediaFileUtils.MEDIA_TYPE_IMAGE
import com.tencent.yolov5ncnn.MediaFileUtils.getOutputMediaFile
import java.io.File
import java.io.IOException
import java.util.concurrent.Executors



class CameraHelper(
    private val activity: Activity,
    private var cameraId: Int,
    private var width: Int = 720,
    private var height: Int = 1280,
) : Camera.PreviewCallback {
    private var surfaceHolder: SurfaceHolder? = null
    private var surfaceTexture: SurfaceTexture? = null
    private var mCamera: Camera? = null
    private var buffer: ByteArray? = null
    private var bytes: ByteArray? = null
    /**
     * 打开相机
     *
     * @param cameraId 后摄 Camera.CameraInfo.CAMERA_FACING_BACK
     *                 前摄 Camera.CameraInfo.CAMERA_FACING_FRONT
     */
    private fun open(cameraId: Int) {
        //获得camera对象
        mCamera = Camera.open(cameraId)

        mCamera?.let { camera ->
            //配置camera的属性
            val parameters = camera.parameters
            //设置预览数据格式为nv21
            parameters.previewFormat = ImageFormat.NV21
            //这是摄像头宽、高
            setPreviewSize(parameters!!)
            // 设置摄像头 图像传感器的角度、方向
            setPreviewOrientation(cameraId)
            camera.parameters = parameters
        }
    }

    /**
     * 切换摄像头
     */
    fun switchCamera() {
        val cameraId = if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            Camera.CameraInfo.CAMERA_FACING_FRONT
        } else {
            Camera.CameraInfo.CAMERA_FACING_BACK
        }
        switchCamera(cameraId)
    }

    /**
     * 切换摄像头
     * @param cameraId 指定摄像头ID
     */
    fun switchCamera(cameraId: Int) {
        this.cameraId = cameraId
        previewAlign()
    }

    private fun previewAlign() {
        stopPreview()
        if (surfaceHolder != null) {
            startPreview(surfaceHolder!!)
        } else {
            startPreview(surfaceTexture!!)
        }
    }

    /**
     * 停止预览
     */
    fun stopPreview() {
        if (mCamera != null) {
            mCamera?.setPreviewCallback(null)
            mCamera?.stopPreview()
            mCamera?.release()
            mCamera = null
        }
    }
    /**
     * 开始预览
     */
    fun startPreview(surfaceHolder: SurfaceHolder) {
//        Log.d("oppo",(surfaceHolder).toString())
        open(cameraId)
        this.surfaceHolder = surfaceHolder
        buffer = ByteArray(width * height * 3 / 2)
        bytes = ByteArray(buffer!!.size)
        //数据缓存区
        mCamera?.addCallbackBuffer(buffer)
        mCamera?.setPreviewCallbackWithBuffer(this)
        //设置预览画面
        mCamera?.setPreviewDisplay(surfaceHolder)
        mCamera?.startPreview()
    }

    fun startPreview(surfaceTexture: SurfaceTexture) {
        open(cameraId)
        this.surfaceTexture = surfaceTexture
        buffer = ByteArray(width * height * 3 / 2)
        bytes = ByteArray(buffer!!.size)
        //数据缓存区
        mCamera?.addCallbackBuffer(buffer)
        mCamera?.setPreviewCallbackWithBuffer(this)
        //设置预览画面
        mCamera?.setPreviewTexture(surfaceTexture)
        mCamera?.startPreview()
    }

    private val threadPool = Executors.newCachedThreadPool()

    /**
     * 拍摄照片
     */
    fun takePicture(completedCallBack: (rotatedBitmap: Bitmap) -> Unit, errorCallBack: (Exception) -> Unit) {
        mCamera?.takePicture(null, null, object : Camera.PictureCallback {
            override fun onPictureTaken(data: ByteArray?, camera: Camera?) {
                previewAlign()

                threadPool.execute {
                    val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE)!!

                    val bitmap : Bitmap
                    try {
                        //路径示例 : /storage/emulated/0/DCIM/QuickExclude/IMG_20230726_135652.jpg
                        bitmap = BitmapFactory.decodeByteArray(data, 0, data!!.size)
                    }catch (e:Exception){
                        errorCallBack.invoke(e)
                        return@execute
                    }

                    val matrix = Matrix()
                    //修正图片方向，这里只是示例，需要根据实际手机方位来决定图片角度
                    matrix.postRotate(if (cameraId == 1) 270F else 90F)
                    if (cameraId == 1) {
                        //postScale在矩阵变换之后进行缩放
                        matrix.postScale(-1F, 1F, bitmap.width / 2F, bitmap.height / 2F)
                    }
                    val rotatedBitmap: Bitmap = Bitmap.createBitmap(
                        bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true
                    )

                    //需要依赖"com.blankj:utilcodex:1.31.1"
//                    ImageUtils.save(rotatedBitmap, pictureFile, Bitmap.CompressFormat.JPEG)
                    completedCallBack.invoke(rotatedBitmap)
                }
            }
        })

    }

    fun getGPS(){

    }
    override fun onPreviewFrame(data: ByteArray, camera: Camera?) {
        onPreviewListener?.onPreviewFrame(data, camera)
        camera!!.addCallbackBuffer(data)
    }

    private fun setPreviewSize(parameters: Camera.Parameters) {
        //获取摄像头支持的宽、高
        val supportedPreviewSizes = parameters.supportedPreviewSizes
        var size = supportedPreviewSizes[0]
        Log.d(TAG, "Camera支持: " + size.width + "x" + size.height)
        //选择一个与设置的差距最小的支持分辨率
        var m: Int = Math.abs(size.height * size.width - width * height)
        supportedPreviewSizes.removeAt(0)
        val iterator: Iterator<Camera.Size> = supportedPreviewSizes.iterator()
        //遍历
        while (iterator.hasNext()) {
            val next = iterator.next()
            Log.d(TAG, "支持 " + next.width + "x" + next.height)
            val n: Int = Math.abs(next.height * next.width - width * height)
            if (n < m) {
                m = n
                size = next
            }
        }
        width = size.width
        height = size.height
        parameters.setPreviewSize(width, height)
        Log.d(TAG, "预览分辨率 width:" + size.width + " height:" + size.height)
    }

    private val mOnChangedSizeListener: OnChangedSizeListener? = null

    private fun setPreviewOrientation(cameraId: Int) {
        val info = Camera.CameraInfo()
        Camera.getCameraInfo(cameraId, info)
        val rotation = activity.windowManager.defaultDisplay.rotation
        var degrees = 0
        when (rotation) {
            Surface.ROTATION_0 -> {
                degrees = 0
                mOnChangedSizeListener?.onChanged(height, width)
            }

            Surface.ROTATION_90 -> {
                degrees = 90
                mOnChangedSizeListener?.onChanged(width, height)
            }

            Surface.ROTATION_180 -> {
                degrees = 180
                mOnChangedSizeListener?.onChanged(height, width)
            }

            Surface.ROTATION_270 -> {
                degrees = 270
                mOnChangedSizeListener?.onChanged(width, height)
            }
        }
        var result: Int
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360
            result = (360 - result) % 360 // compensate the mirror
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360
        }
        //设置角度, 参考源码注释
        mCamera!!.setDisplayOrientation(result)
    }

    private lateinit var mediaRecorder: MediaRecorder
    private val handle = Handler(Looper.getMainLooper())

    /**
     * 开始录像
     */
    fun startVideo(path: String) {
        mediaRecorder = MediaRecorder()
        //解锁相机,以供 MediaRecorder 使用
        mCamera?.unlock()
        //设置要用于视频捕获的相机
        mediaRecorder.setCamera(mCamera)
        //设置音频源
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
        //设置视频源
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA)
        //设置视频的输出格式和编码
        mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH))
        //设置输出视频播放的方向，这里只是示例，需要根据实际手机方位来决定角度
        mediaRecorder.setOrientationHint(if (cameraId == 1) 270 else 90)
        //设置输出文件
        mediaRecorder.setOutputFile(path)
        //指定 SurfaceView 预览布局元素
        mediaRecorder.setPreviewDisplay(surfaceHolder!!.surface)
        try {
            mediaRecorder.prepare()
        } catch (e: IOException) {
            e.printStackTrace()
            releaseMediaRecorder()
        }

        handle.postDelayed({
            try {
                mediaRecorder.start()
            } catch (e: IOException) {
                e.printStackTrace()
                releaseMediaRecorder()
            }
        }, 10)
    }

    /**
     * 释放资源
     */
    fun releaseMediaRecorder() {
        if (mediaRecorder != null) {
            mediaRecorder.reset() // 清除配置
            mediaRecorder.release()
            //mediaRecorder = null
            mCamera?.lock()
        }
    }

    /**
     * 停止录像
     */
    fun stopVideo() {
        mediaRecorder.stop()
        mediaRecorder.release()
        mCamera?.lock()
    }

    interface OnChangedSizeListener {
        fun onChanged(width: Int, height: Int)
    }

    fun interface OnPreviewListener {
        fun onPreviewFrame(data: ByteArray, camera: Camera?)
    }

    private var onPreviewListener: OnPreviewListener? = null

    /**
     * 设置预览监听
     */
    fun setOnPreviewListener(listener: OnPreviewListener) {
        this.onPreviewListener = listener
    }

    companion object {
        private const val TAG = "CAMERA_HELPER"
    }
}
